package com.siyoumi.app.modules.app_ess.service;

import com.siyoumi.app.entity.*;
import com.siyoumi.app.modules.app_ess.vo.*;
import com.siyoumi.app.modules.user.service.SvcSysUser;
import com.siyoumi.app.modules.user.vo.SysUserAudit;
import com.siyoumi.app.service.EssModuleUserService;
import com.siyoumi.app.service.EssUserService;
import com.siyoumi.component.XApp;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XRedis;
import com.siyoumi.component.XSpringContext;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.mybatispuls.JoinWrapperPlus;
import com.siyoumi.service.IWebService;
import com.siyoumi.util.XJson;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import com.siyoumi.validator.annotation.HasAnyText;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

//学生老师
@Slf4j
@Service
public class SvcEssUser
        implements IWebService {
    static public SvcEssUser getBean() {
        return XSpringContext.getBean(SvcEssUser.class);
    }

    static public EssUserService getApp() {
        return EssUserService.getBean();
    }

    public Boolean isTeacher(EssUser entityUser) {
        return entityUser.getEuser_type() == 1;
    }

    public EssUser getEntity(String id) {
        return XRedis.getBean().getAndSetData(getApp().getEntityCacheKey(id), k -> {
            return getApp().loadEntity(id);
        }, EssUser.class);
    }

    /**
     * 老师列表
     */
    public List<Map<String, Object>> getTeacherList() {
        JoinWrapperPlus<EssUser> query = listQuery(1);
        query.select("user_id", "user_name");

        return getApp().getMaps(query);
    }

    public JoinWrapperPlus<EssUser> listQuery(Integer type) {
        JoinWrapperPlus<EssUser> query = listQuery(InputData.getIns());
        query.eq("euser_type", type);
        return query;
    }

    public JoinWrapperPlus<EssUser> listQuery() {
        return listQuery(InputData.getIns());
    }

    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<EssUser> listQuery(InputData inputData) {
        String name = inputData.input("name");
        String classId = inputData.input("class_id");
        String type = inputData.input("type");

        JoinWrapperPlus<EssUser> query = getApp().join();
        query.join(SysUser.table(), SysUser.tableKey(), EssUser.tableKey());
        query.eq("euser_x_id", XHttpContext.getX());

        if (XStr.hasAnyText(type)) { //0：学生；1：老师；
            query.eq("euser_type", type);
        } else {
            query.in("euser_type", 0, 1);
        }
        if (XStr.hasAnyText(name)) { //名称
            query.like("user_name", name);
        }
        if (XStr.hasAnyText(classId)) { //班级
            String sqlExists = "SELECT 1 FROM wx_app_x.t_ess_class_user WHERE ecu_class_id = {0} AND ecu_uid = user_id";
            query.exists(sqlExists, classId);
        }

        return query;
    }

    public XReturn edit(InputData inputData, VaEssUser vo) {
        List<String> ignoreField = new ArrayList<>();
        if (inputData.isAdminEdit()) {
            //ignoreField.add("eclass_acc_id");
        }

        return XApp.getTransaction().execute(status -> {
            XReturn r = getApp().saveEntity(inputData, vo, false, ignoreField);
            SysUser entityUser = SvcSysUser.getApp().getEntity(vo.getEuser_id());
            SysUser entityUserUpdate = new SysUser();
            XBean.copyProperties(vo, entityUserUpdate);
            entityUserUpdate.setUser_id(vo.getEuser_id());
            entityUserUpdate.setUser_x_id(XHttpContext.getX());
            if (entityUser == null) {
                //新建，设置初始密码
                entityUserUpdate.setUser_pwd(XApp.encPwd(XHttpContext.getX(), SvcSysUser.defPwdNum()));
            }
            SvcSysUser.getApp().saveOrUpdatePassEqualField(entityUser, entityUserUpdate);

            //清缓存
            getApp().delEntityCache(vo.getEuser_id());
            SvcSysUser.getApp().delEntityCache(vo.getEuser_id());

            //生效
            SysUserAudit audit = new SysUserAudit();
            audit.setIds(List.of(vo.getEuser_id()));
            audit.setEnable(1);
            SvcSysUser.getBean().audit(audit);
            return r;
        });
    }

    /**
     * 删除
     */
    @SneakyThrows
    @Transactional(propagation = Propagation.MANDATORY)
    public XReturn delete(List<String> ids) {
        XReturn r = XReturn.getR(0);

        getApp().delete(ids);

        return r;
    }

    /**
     * 标记分班状态
     *
     * @param uid
     * @param set
     */
    public void updateSetClass(String uid, Integer set) {
        EssUser entityUserUpdate = new EssUser();
        entityUserUpdate.setEuser_id(uid);
        entityUserUpdate.setEuser_set_class(set);
        getApp().updateById(entityUserUpdate);
    }


    /**
     * 批量添加
     *
     * @param vo
     */
    @Transactional(rollbackFor = Exception.class)
    public XReturn addBatch(VoEssUserAddBatch vo) {
        List<VaEssUser> importList = vo.getUpload_data();
        if (importList == null || importList.isEmpty()) {
            return EnumSys.ERR_VAL.getR("导入数据异常");
        }
        Integer rowIndex = 1;
        for (VaEssUser item : importList) {
            XValidator.isNullOrEmpty(item.getUser_username(), rowIndex + "：帐号不能为空");
            XValidator.isNullOrEmpty(item.getUser_name(), rowIndex + "：姓名不能为空");
            //XValidator.isNullOrEmpty(item.getClass_id(), rowIndex + "：班级ID不能为空");
        }
        //检查班级ID
        List<String> classIds = importList.stream()
                .filter(item -> XStr.hasAnyText(item.getClass_id()))
                .map(item -> item.getClass_id()).collect(Collectors.toList())
                .stream().distinct()
                .collect(Collectors.toList());
        {
            List<EssClass> listClass = SvcEssClass.getApp().get(classIds);
            if (listClass.size() != classIds.size()) {
                List<String> dbClassIds = listClass.stream().map(item -> item.getKey()).collect(Collectors.toList());
                List<String> notExistsClassIds = classIds.stream().filter(item -> dbClassIds.contains(item)).collect(Collectors.toList());
                //EssClass notExistsClass = classIds.stream().filter(item -> !listClass.contains(item)).findFirst().orElse(null);
                return EnumSys.ERR_VAL.getR(XStr.format("导入数据班级ID异常，{0}，不存在"
                        , notExistsClassIds.stream().collect(Collectors.joining(",")))
                );
            }
        }
        //检查帐号是否存在
        {
            List<String> usernameList = importList.stream().map(item -> item.getUser_username()).collect(Collectors.toList());
            JoinWrapperPlus<SysUser> query = SvcSysUser.getApp().join();
            query.in("user_username", usernameList);
            SysUser entity = SvcSysUser.getApp().first(query);
            if (entity != null) {
                return EnumSys.ERR_VAL.getR(XStr.format("导入数据帐号异常，{0}，帐号已存在", entity.getUser_username()));
            }
        }

        List<EssUser> list = new ArrayList<>();
        List<SysUser> listSys = new ArrayList<>();
        for (VaEssUser item : importList) {
            EssUser entity = new EssUser();
            XBean.copyProperties(item, entity);
            entity.setEuser_x_id(XHttpContext.getX());
            entity.setEuser_id(XApp.getStrID());
            list.add(entity);

            SysUser entitySysUser = new SysUser();
            XBean.copyProperties(item, entitySysUser);
            entitySysUser.setUser_id(entity.getEuser_id());
            entitySysUser.setUser_x_id(entity.getEuser_x_id());
            entitySysUser.setUser_pwd(XApp.encPwd(XHttpContext.getX(), SvcSysUser.defPwdNum())); //密码
            entitySysUser.setUser_phone(SvcSysUser.tempPhone(entity.getEuser_id()));
            listSys.add(entitySysUser);

            item.setEuser_id(entity.getEuser_id());
        }
        getApp().saveBatch(list);
        SvcSysUser.getApp().saveBatch(listSys);

        if ("0".equals(vo.getEuser_type())) { //学生才会分班
            //分班
            for (String classId : classIds) {
                List<VaEssUser> listByClassId = importList.stream().filter(item -> classId.equals(item.getClass_id())).collect(Collectors.toList());
                if (listByClassId.isEmpty()) {
                    continue;
                }
                //分班
                {
                    List<String> uids = listByClassId.stream().map(item -> item.getEuser_id()).collect(Collectors.toList());
                    VoEssAddStudent voEssAddStudent = new VoEssAddStudent();
                    voEssAddStudent.setClass_id(classId);
                    voEssAddStudent.setUids(uids);
                    XReturn r = SvcEssClass.getBean().studentAddClass(voEssAddStudent);
                    XValidator.err(r);
                }
            }
        }

        for (EssUser entityUser : list) {
            //生效
            SysUserAudit audit = new SysUserAudit();
            audit.setIds(List.of(entityUser.getEuser_id()));
            audit.setEnable(1);
            SvcSysUser.getBean().audit(audit);
        }

        return EnumSys.OK.getR();
    }


    /**
     * 更新学生，次数和分数
     *
     * @param uid
     * @param type
     * @param fun
     */
    public void updateTotal(String uid, String moduleId, String type, Integer fun) {
        SvcEssUser.getApp().update()
                .setSql(XStr.format("euser_{0}_count = euser_{0}_count + 1,euser_{0}_fun = euser_{0}_fun + {1}", type, fun.toString()))
                .eq("euser_id", uid)
                .update();
        SvcEssUser.getApp().delEntityCache(uid);
        EssModuleUserService.getBean();

        if (!"test0".equals(type)) { //评价不跟模块
            //更新模块数据
            EssModuleUser entityModuleUser = getOrNewModuleUser(moduleId, uid);
            EssModuleUserService.getBean().update()
                    .setSql(XStr.format("emuser_{0}_count = emuser_{0}_count + 1,emuser_{0}_fun = emuser_{0}_fun + {1}", type, fun.toString()))
                    .eq(EssModuleUser.tableKey(), entityModuleUser.getKey())
                    .update();
        }
    }

    public JoinWrapperPlus<EssModuleUser> listModuleUserQuery() {
        return listModuleUserQuery(InputData.getIns());
    }

    /**
     * select
     *
     * @return query
     */
    public JoinWrapperPlus<EssModuleUser> listModuleUserQuery(InputData inputData) {
        String uid = inputData.input("uid");

        JoinWrapperPlus<EssModuleUser> query = EssModuleUserService.getBean().join();
        query.eq("emuser_x_id", XHttpContext.getX());

        if (XStr.hasAnyText(uid)) { //uid
            query.eq("emuser_uid", uid);
        }

        return query;
    }


    public EssModuleUser getOrNewModuleUser(String moduleId, String uid) {
        JoinWrapperPlus<EssModuleUser> query = listModuleUserQuery();
        query.eq("emuser_module_id", moduleId)
                .eq("emuser_uid", uid);
        EssModuleUser entityUser = EssModuleUserService.getBean().first(query);
        if (entityUser == null) {
            entityUser = new EssModuleUser();
            entityUser.setEmuser_x_id(XHttpContext.getX());
            entityUser.setAutoID();
            entityUser.setEmuser_module_id(moduleId);
            entityUser.setEmuser_uid(uid);
            EssModuleUserService.getBean().save(entityUser);
        }

        return entityUser;
    }
}
